import {Fragment} from 'react'
import {Card, CardProps} from 'antd'
import {TreeNode, createResource} from '@swiftease/designable-core'
import {
    useTreeNode,
    TreeNodeWidget,
    DroppableWidget,
    useNodeIdProps,
    DnFC, useCssInJs,
} from '@swiftease/designable-react'
import {ArrayBase} from '@swiftease/formily-antd-v5'
import {observer} from '@formily/react'
import {LoadTemplate} from '../../common/LoadTemplate'
import {useDropTemplate} from '../../hooks'
import {
    hasNodeByComponentPath,
    queryNodesByComponentPath,
    createEnsureTypeItemsNode,
    findNodeByComponentPath,
    createNodeId,
} from '../../shared'
import {createArrayBehavior} from '../ArrayBase'
import cls from 'classnames'
import {genArrayCardsStyle} from "./styles";
import React from 'react'

const ensureObjectItemsNode = createEnsureTypeItemsNode('object')

const isArrayCardsOperation = (name: string) =>
    name === 'ArrayCards.Remove' ||
    name === 'ArrayCards.MoveDown' ||
    name === 'ArrayCards.MoveUp'

export const ArrayCards: DnFC<CardProps> = observer((props) => {
    const node = useTreeNode()
    const nodeId = useNodeIdProps()
    const designer = useDropTemplate('ArrayCards', (source) => {

        const indexNode = new TreeNode({
            componentName: node.componentName,
            props: {
                type: 'void',
                'x-component': 'ArrayCards.Index',
            },
        })
        const additionNode = new TreeNode({
            componentName: node.componentName,
            props: {
                type: 'void',
                title: 'Addition',
                'x-component': 'ArrayCards.Addition',
            },
        })
        const removeNode = new TreeNode({
            componentName: node.componentName,
            props: {
                type: 'void',
                title: 'Addition',
                'x-component': 'ArrayCards.Remove',
            },
        })
        const moveDownNode = new TreeNode({
            componentName: node.componentName,
            props: {
                type: 'void',
                title: 'Addition',
                'x-component': 'ArrayCards.MoveDown',
            },
        })
        const moveUpNode = new TreeNode({
            componentName: node.componentName,
            props: {
                type: 'void',
                title: 'Addition',
                'x-component': 'ArrayCards.MoveUp',
            },
        })

        const objectNode = new TreeNode({
            componentName: node.componentName,
            props: {
                type: 'object',
            },
            children: [indexNode, ...source, removeNode, moveDownNode, moveUpNode],
        })
        return [objectNode, additionNode]
    })
    const {hashId, wrapSSR} = useCssInJs({prefix: "dn-array-cards", styleFun: genArrayCardsStyle})
    const renderCard = () => {
        if (node.children.length === 0) return <DroppableWidget/>
        const additions = queryNodesByComponentPath(node, [
            'ArrayCards',
            'ArrayCards.Addition',
        ])
        const indexes = queryNodesByComponentPath(node, [
            'ArrayCards',
            '*',
            'ArrayCards.Index',
        ])
        const operations = queryNodesByComponentPath(node, [
            'ArrayCards',
            '*',
            isArrayCardsOperation,
        ])
        const children = queryNodesByComponentPath(node, [
            'ArrayCards',
            '*',
            (name) => name.indexOf('ArrayCards.') === -1,
        ])
        return (
            <ArrayBase disabled>
                <ArrayBase.Item index={0} record={null}>
                    <Card
                        {...props}
                        title={
                            <Fragment>
                                {indexes.map((node, key) => (
                                    <TreeNodeWidget key={key} node={node}/>
                                ))}
                                <span data-content-editable="x-component-props.title">
                  {props.title}
                </span>
                            </Fragment>
                        }
                        className={cls('ant-formily-array-cards-item', props.className)}
                        extra={
                            <Fragment>
                                {operations.map((node) => (
                                    <TreeNodeWidget key={node.id} node={node}/>
                                ))}
                                {props.extra}
                            </Fragment>
                        }
                    >
                        <div {...createNodeId(designer, ensureObjectItemsNode(node).id)}>
                            {children.length ? (
                                children.map((node) => (
                                    <TreeNodeWidget key={node.id} node={node}/>
                                ))
                            ) : (
                                <DroppableWidget hasChildren={false}/>
                            )}
                        </div>
                    </Card>
                </ArrayBase.Item>
                {additions.map((node) => (
                    <TreeNodeWidget key={node.id} node={node}/>
                ))}
            </ArrayBase>
        )
    }

    return wrapSSR(
        <div {...nodeId} className={cls("dn-array-cards", hashId)}>
            {renderCard()}
            <LoadTemplate
                actions={[
                    {
                        title: node.getMessage('addIndex'),
                        icon: 'AddIndex',
                        onClick: () => {
                            if (
                                hasNodeByComponentPath(node, [
                                    'ArrayCards',
                                    '*',
                                    'ArrayCards.Index',
                                ])
                            )
                                return
                            const indexNode = new TreeNode({
                                componentName: node.componentName,
                                props: {
                                    type: 'void',
                                    'x-component': 'ArrayCards.Index',
                                },
                            })
                            ensureObjectItemsNode(node).append(indexNode)
                        },
                    },

                    {
                        title: node.getMessage('addOperation'),
                        icon: 'AddOperation',
                        onClick: () => {
                            const oldAdditionNode = findNodeByComponentPath(node, [
                                'ArrayCards',
                                'ArrayCards.Addition',
                            ])
                            if (!oldAdditionNode) {
                                const additionNode = new TreeNode({
                                    componentName: node.componentName,
                                    props: {
                                        type: 'void',
                                        title: 'Addition',
                                        'x-component': 'ArrayCards.Addition',
                                    },
                                })
                                ensureObjectItemsNode(node).insertAfter(additionNode)
                            }
                            const oldRemoveNode = findNodeByComponentPath(node, [
                                'ArrayCards',
                                '*',
                                'ArrayCards.Remove',
                            ])
                            const oldMoveDownNode = findNodeByComponentPath(node, [
                                'ArrayCards',
                                '*',
                                'ArrayCards.MoveDown',
                            ])
                            const oldMoveUpNode = findNodeByComponentPath(node, [
                                'ArrayCards',
                                '*',
                                'ArrayCards.MoveUp',
                            ])
                            if (!oldRemoveNode) {
                                ensureObjectItemsNode(node).append(
                                    new TreeNode({
                                        componentName: node.componentName,
                                        props: {
                                            type: 'void',
                                            'x-component': 'ArrayCards.Remove',
                                        },
                                    })
                                )
                            }
                            if (!oldMoveDownNode) {
                                ensureObjectItemsNode(node).append(
                                    new TreeNode({
                                        componentName: node.componentName,
                                        props: {
                                            type: 'void',
                                            'x-component': 'ArrayCards.MoveDown',
                                        },
                                    })
                                )
                            }
                            if (!oldMoveUpNode) {
                                ensureObjectItemsNode(node).append(
                                    new TreeNode({
                                        componentName: node.componentName,
                                        props: {
                                            type: 'void',
                                            'x-component': 'ArrayCards.MoveUp',
                                        },
                                    })
                                )
                            }
                        },
                    },
                ]}
            />
        </div>
    )
})

ArrayBase.mixin(ArrayCards)

ArrayCards.Behavior = createArrayBehavior('ArrayCards')

ArrayCards.Resource = createResource({
    icon: 'ArrayCardsSource',
    elements: [
        {
            componentName: 'Field',
            props: {
                type: 'array',
                'x-decorator': 'FormItem',
                'x-component': 'ArrayCards',
                'x-component-props': {
                    title: `Title`,
                },
            },
        },
    ],
})
